package com.uyaer.wheel.game.map
{
	
	import com.uyaer.wheel.common.Common;
	import com.uyaer.wheel.common.Config;
	import com.uyaer.wheel.common.Platform;
	import com.uyaer.wheel.common.UserData;
	import com.uyaer.wheel.events.EventType;
	import com.uyaer.wheel.game.Game;
	import com.uyaer.wheel.nape.BodyPool;
	import com.uyaer.wheel.texture.TexturePool;
	import com.uyaer.wheel.utils.Utils;
	
	import flash.geom.Point;
	
	import nape.phys.Body;
	
	import starling.display.Image;

	/**
	 *随机地图 
	 * @author hc
	 * 
	 */
	public class RandomMap implements IMap
	{
		/**
		 *格子真实大小 
		 */		
		public var SIZE:int = 32;
		/**
		 *行数 
		 */		
		private var ROW:int;
		/**
		 *列数 
		 */		
		private var COL:int;
		private var MAX_OFFSET_SIZE:int = 96; 
		private var MAX_OFFSET_COUNT:int = 3; 
		/**
		 *地图信息 
		 */		
		private var map:Array = new Array();
		private var velocity:Number = 1; //地图自己移动速度
		private var isAutoRuning:Boolean = true; //是否自动运行
		private var offset:Number = 0;
		private var mapAddIndex:int = 0;
		public var mapLineIndex:int = 0;
		public var removeIndex:int = -2;
		public var gameContainer:Game;
		
		private var rang:Point = new Point();
		private static var m_instance:RandomMap;

		private var startIndex:int;

		private var endIndex:int;

		private var popP:Number;

		private var starP:Number;
		
		public function RandomMap()
		{
			ROW = Math.ceil(Common.H / SIZE);
			COL = Math.ceil(Common.W / SIZE);
			MAX_OFFSET_SIZE = SIZE * MAX_OFFSET_COUNT;
		}
		
		public static function get instance():RandomMap{
			return m_instance ||= new RandomMap();
		}
		
		/**
		 *初始化地图信息 
		 */	
		private function init():void{
			var bottom:int = ROW/4;
			var j:int = 0;
			var line:Array;
			for(var i:int = 0 ; i < ROW+MAX_OFFSET_COUNT+1 ; i ++){
				j = 0;
				line = new Array();
				if(i < bottom ){
					for( ; j < COL ; j ++){
						line.push(MapCellType.ROCK);
					}
				}else{
					for( ; j < COL ; j ++){
						if(j == 0 || j == COL -1){
							line.push(MapCellType.ROCK);
						}else{
							line.push(MapCellType.NONE);
						}
					}
				}
				map.push(line);
				createBody(line);
				mapLineIndex++;
				mapAddIndex = mapLineIndex/MAX_OFFSET_COUNT;
			}
		}
		
		/**
		 * 产生下一行
		 */		
		public function next():void{
			for(var i:int = 0 ; i < MAX_OFFSET_COUNT ; i ++){
				var topLine:Array = map[map.length-1];
				var line:Array = calStartAndEnd(topLine);
				this.createBody(line);
				mapLineIndex ++;
			}
			mapAddIndex ++;
		}
		
		private function calStartAndEnd(prev:Array):Array{
			if(prev == null){
				throw "array is null";
			}else{
				var line:Array = this.preAline(prev);
				var emptyIndex:int = getEmptyCell(prev);
				//计算起点和终点的可能
				this.calRang(line,emptyIndex); 
				//修饰，最终生成line
				line = createLine(startIndex, endIndex,line);
				//检查路线是否可以通过
				if(Config.debug){
					checkLineValidate(prev,line,emptyIndex);
				}
				map.push(line);
				return line;
			}
		}
		
		/**
		 *取的可能的长度 
		 * @param line
		 * @param emptyIndex
		 * 
		 */		
		private function calRang(line:Array,emptyIndex:int):void{
			//还未确定数量时可以取得的范围，用于确定生成空白的数量
			var min:int = emptyIndex;
			var max:int = emptyIndex;
			var index:int = 1;
			//先计算左边值范围
			while(emptyIndex-index > 0 && line[emptyIndex-index] == MapCellType.NONE){
				min = emptyIndex-index;
				index++;
			}
			//计算右边范围
			index = 1;
			while((emptyIndex+index) < (COL-1) && line[emptyIndex+index] == MapCellType.NONE){
				max = emptyIndex+index;
				index++;
			}
			//确定生成了几个空白（2个以上）
			var countMax:int = max - min + 1;
			var count:int = Utils.rangInt(2,countMax); 
			//最终再次确定生成范围起点和终点的可能
			var minIndex:int = Math.max(min, emptyIndex - count + 1); 
			var maxIndex:int = Math.min(max, emptyIndex + count - 1);
			
			var temp:int = Utils.rangInt(minIndex,maxIndex-count+1);
			//最终去顶起点和终点
			startIndex = temp;
			endIndex = startIndex+count-1;
			
			if(Config.debug){
				if(startIndex ==0 || endIndex == COL-1 || emptyIndex < startIndex || emptyIndex>endIndex){
					debug();
					throw "out of bounds!";
				}
				for(var i:int = startIndex; i <= endIndex;i++){
					if(line[i]!=MapCellType.NONE){
						throw "计算错误？";
					}
				}
			}
		}
		
		/**
		 *检查路线是否可以通过 
		 * @param prev
		 * 
		 */		
		private function checkLineValidate(prev:Array,line:Array,emptyIndex:int):void{
			var flag:Boolean = false;
			for(var i:int  = startIndex ; i <= endIndex ; i ++){
				if(prev[i] == 0 || prev[i]>100){
					flag = true;
				}
			}
			if(!flag){
				throw "路线不通过";
			}
			var emptyMap:Array = new Array();
			for(i = 0 ; i < line.length; i ++){
				if(line[i] == MapCellType.NONE || line[i]>100){
					if(emptyMap.length>0){
						if(emptyMap[emptyMap.length-1]+1!=i){
							throw "0 has more one block!!";
						}
					}
					emptyMap.push(i);
				}
			}
		}
		
		/**
		 *根据上一行，预先获得一段，先处理障碍物 
		 * @param prevLine
		 * 
		 */		
		private function preAline(prevLine:Array):Array{
			var line:Array = [];
			for(var i:int = 0 ; i < COL ; i ++){
				if(prevLine[i] == MapCellType.TREE3x2){
					line.push(MapCellType.SPACE_HOLDER);
					line.push(MapCellType.SPACE_HOLDER);
					line.push(MapCellType.SPACE_HOLDER);
					i += 2;
					continue;
				}
				if(prevLine[i] == MapCellType.TREE2x2){
					line.push(MapCellType.SPACE_HOLDER);
					line.push(MapCellType.SPACE_HOLDER);
					i ++;
					continue;
				}else{
					line.push(MapCellType.NONE);
				}
			}
			line.length = COL;
			return line;
		}
		
		private function createLine(start:int, end:int,line):Array{
			var i:int = 0;
			for( ; i < COL ; i ++){
				if(i < start || i > end){ //不可以通过
					if(Utils.probability(0.1)){ //可以使用2阶段地图
						if((i+3<start || i>end) && Utils.probability(0.5)){ //可以占用3格的
							line[i] =MapCellType.TREE3x2;
							line[i+1] = MapCellType.SPACE_HOLDER;
							line[i+2] = MapCellType.SPACE_HOLDER;
							i+=2;
						}else if((i+2<start || i>end) && Utils.probability(0.5)){ //使用占用2个的
							switch(Utils.rangInt(1,2)){
								case 1:
									line[i] = MapCellType.TREE2x2;
									break;
								case 2:
									line[i] = MapCellType.TREE2x1;
									break;
							}
							line[i+1] = MapCellType.SPACE_HOLDER;
							i++;
						}else{ //使用一阶地图
							switch(Utils.rangInt(1,2)){
								case 1:
									line[i] = MapCellType.ROCK;
									break;
								case 2:
									line[i] = MapCellType.TREE1x1;
									break;
							}
						}
					}else{ //使用一阶地图
						switch(Utils.rangInt(1,2)){
							case 1:
								line[i] = MapCellType.ROCK;
								break;
							case 2:
								line[i] = MapCellType.TREE1x1;
								break;
						}
					}
				}else{ //设置为pass的
//					if(Config.platform==Platform.MOBILE){
//						popP = 0.0001*UserData.me.level+0.05;
//					}else{
//						popP = 0;
//					}
					popP = 0;
					starP = popP+0.085;
					var r:Number = Math.random();
					if(r<popP){
						line[i] = MapCellType.POP; //设置泡泡
					}else if(r<starP){
						line[i] = MapCellType.STAR; //设置星星
					}
				}
			}
			return line;
		}
		
		/**
		 *获得一个空的各自索引 
		 * @param prev
		 * @return 
		 * 
		 */		
		private function getEmptyCell(prev:Array):int{
			var emptyMap:Array = new Array();
			for (var i:int = 0; i < prev.length; i++){
				if(prev[i] == MapCellType.NONE || prev[i]>100){
					emptyMap.push(i);
				}
			}
			if(emptyMap.length==0){
				throw "len is 0!!";
			}
			return emptyMap[Utils.rangInt(0,emptyMap.length-1)];
		}
		/**
		 *获得一个空的各自索引 但是尽量靠近中间的部位
		 * @param prev
		 * @return 
		 * 
		 */		
		private function getCenterEmptyCell(prev:Array):int{
			var emptyMap:Array = new Array();
			for (var i:int = 0; i < prev.length; i++){
				if(prev[i] == MapCellType.NONE || prev[i]>100){
					emptyMap.push(i);
				}
			}
			if(emptyMap.length==0){
				throw "len is 0!!";
			}
			var index:int = emptyMap[0];
			var min:Number = Number.MAX_VALUE;
			var d:Number;
			for (i = 1; i < emptyMap.length; i++){
				d = Math.abs(emptyMap[i]-COL*0.5);
				if(d<min){
					index = emptyMap[i];
					min = d;
				}
			}
			
			return index;
		}
		public function pop():void{
			map.splice(0,MAX_OFFSET_COUNT);
			removeIndex++;
		}
		/**
		 *移动 
		 */		
		public function move(d:Number = 0):void{
			var v:Number = Math.abs(d);
			if(isAutoRuning){
				v = Math.max(v,velocity);
			}
			offset+=v;
			if(offset >= MAX_OFFSET_SIZE){
				offset = offset - MAX_OFFSET_SIZE;
				this.next();
				this.pop();
			}
			if(Config.isUp){
				gameContainer.y += v;
			}else{
				gameContainer.y -= v;
			}
			gameContainer.stage.dispatchEventWith(EventType.MAP_MOVE,false,v);
		}
		
		/**
		 *创建刚体 
		 */		
		private function createBody(line:Array):void{
			var body:Body = null;
			var texture:Image = null;
			var len:int;
			for(var i:int = 0 ; i < line.length ; i ++){
				len = 1;
				if(line[i] != MapCellType.NONE){
					if(line[i] == MapCellType.TREE2x1 || line[i] == MapCellType.TREE2x2){
						len = 2;
					}else if(line[i] == MapCellType.TREE3x2){
						len = 3;
					}else if(line[i] == MapCellType.ROCK){
						while(i+len<line.length && line[i] == line[i+len]){
							len++;
						}
					}
					if(Config.isUp){
						body = BodyPool.getBox(i*SIZE,-mapLineIndex*SIZE+Common.H,SIZE*len,SIZE,line[i]);
					}else{
						body = BodyPool.getBox(i*SIZE,mapLineIndex*SIZE,SIZE*len,SIZE,line[i]);
					}
					texture = TexturePool.getOne(line[i],SIZE*len);
					if(texture){
						texture.x = body.bounds.x;
						texture.y = body.bounds.y;
						if(Config.isUp){
							gameContainer.addChildAt(texture,1);
						}else{
							gameContainer.addChild(texture);
						}
					}
					if(line[i] == MapCellType.STAR || line[i] == MapCellType.POP){
						body.cbTypes.add(Common.awardCbType);
						body.shapes.at(0).sensorEnabled = true;
					}else{
						body.cbTypes.add(Common.barCbType);
					}
					body.userData.data = {"textureType":line[i],"texture":texture,"removeIndex":mapAddIndex};
					i += len-1;
				}
			}
		}
		
		public function getCenterEmptyPos():Point{
			var centerIndex:int = int(map.length/2);
			var line:Array = map[centerIndex];
			var index:int = getCenterEmptyCell(line);
			return new Point(index*SIZE,-(mapLineIndex-centerIndex)*SIZE+Common.H);
		}
		
		public function start(game:Game):void
		{
			this.gameContainer = game;
			this.init();
		}
		
		public function reLayout():void
		{
		}
		
		public function stop():void{
			map.length = 0;
			offset = 0;
			mapAddIndex = 0;
			mapLineIndex = 0;
			removeIndex = -2;
			gameContainer = null;
		}
		
		public function debug():void{
			for (var i:int = map.length - 1 ; i > 0; i--){
				trace(map[i]);
			}
		}
	}
}